package ao.util.text;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: aostrovsky
 * Date: 20-Jul-2009
 * Time: 11:12:34 AM
 *
 * Doesn't work for complicated CVS cases, for a proper Comma Separated Value
 *  (CSV) library check out OpenCSV: http://opencsv.sourceforge.net/
 *
 */
public class Csv
{
    //-------------------------------------------------------------------------
    public static void main(String[] args)
    {
        String sample = "";

        sample += "hello,world\n";
        sample += "\"foo,bar\",baz\n";
//        sample += "\"a,b,c\",\"a\"\"b\"\"c\"\n";


        System.out.println("Parsing:\n" + sample);
        for (String line : sample.split("(\r|\n)+"))
        {
            System.out.println("In: " + line);

            for (String col : fromCvs( line ))
            {
                System.out.println( col );
            }
        }
    }


    //-------------------------------------------------------------------------
    private Csv() {}


    //-------------------------------------------------------------------------
    private static final Pattern CVS_PATTERN = Pattern.compile(
            "\"([^\"]+?)\",?|([^,]+),?|,");


    //-------------------------------------------------------------------------
    private static final Pattern SAFE_CHARS_PAT = Pattern.compile(
            "^[\\d\\w ]*$");


    //-------------------------------------------------------------------------
    public static String toCsv(Iterable<String> row)
    {
        List<String> asList = new ArrayList<String>();
        for (String cell : row) {
            asList.add( cell );
        }
        return toCsv(asList.toArray(
                new String[ asList.size() ]));
    }
    
    public static String toCsv(String... row)
    {
        StringBuilder str = new StringBuilder();

        boolean isFirst = true;
        for (String val : row)
        {
            if (! isFirst) {
                str.append(',');
            }
            str.append(encode(val));
            isFirst = false;
        }

        return str.toString();
    }


    //--------------------------------------------------------------------
    private static List<String> fromCvs(String line)
    {
        List<String> list = new ArrayList<String>();
        Matcher m = CVS_PATTERN.matcher(line);

        while (m.find())
        {
            String match = m.group();
            if (match == null)
            {
                break;
            }

            if (match.endsWith(",")) {  // trim trailing ,
                match = match.substring(0, match.length() - 1);
            }

            if (match.startsWith("\"")) { // assume also ends with
                match = match.substring(1, match.length() - 1);
            }

            if (match.length() == 0)
            {
                match = null;
            }

            list.add(match);
        }

        return list;
    }

//    public static int fromCsv(
//            String data, int offset, List<String> into)
//    {
//        StringBuilder field   = new StringBuilder();
//        boolean       inQuote = false;
//        for (int i = offset; i < data.length(); i++)
//        {
//            char c = data.charAt( i );
//
////            if
//
//        }
//
//        return -1;
//    }


    //--------------------------------------------------------------------
    private static String encode(String csvField)
    {
        if (SAFE_CHARS_PAT.matcher(csvField).matches()) {
            return csvField;
        }

        StringBuilder str = new StringBuilder();
        str.append('"');
        str.append( csvField.replaceAll("\"", "\"\"") );
        str.append('"');
        return str.toString();
    }
}
